home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / async.zip / INTCOMM.C < prev    next >
C/C++ Source or Header  |  1986-10-10  |  3KB  |  145 lines

  1. /*M
  2.    intcomm - implement common code for interrupt handlers that call
  3.    C routines
  4.  */
  5. #include "interrup.h"
  6.  
  7. int_handler template =
  8. {
  9. #ifndef MPU80186
  10.     { 0x53,                /* push bx */ 
  11.       0x06,                /* push es */ },
  12. #else
  13.     { 0x60                 /* pusha   */ },
  14. #endif
  15.     { 0xBB, 0x0000        /* mov bx, seg svc */ },
  16.     { 0x8E, 0xC3        /* mov es,bx    */ },
  17.     { 0xBB,0x0000        /* mov bx,offset svc */ },
  18.     { 0x9A,0x0000,0x0000/* call common far */ },
  19. #ifndef MPU80186
  20.     { 0x07,                /* pop es */ 
  21.       0x5B,                /* pop bx */ },
  22. #else
  23.     { 0x61                 /* popa   */ },
  24. #endif
  25.       0xCF,                /* iret */
  26.       0x0000,                /* old_offset */
  27.       0x0000,             /* old_segment */
  28.       0x0000,             /* new_offset */
  29.       0x0000              /* new_segment */
  30. };
  31.  
  32. int_handler *
  33. setup_handler(int_num,handler,chain_int)
  34.     int int_num;        /* number of the interrupt to steal */
  35.     void (*handler)();  /* C function to attach to interrupt */
  36.     int chain_int;        /* 1 if you're supposed to call old service
  37.                            when you're done
  38.                             0 if you're supposed to replace it */
  39. {
  40.     union
  41.     {
  42.         struct
  43.         {
  44.             unsigned offset,segment;
  45.         } parts;
  46.         long vector;
  47.     } int_vector;
  48.     extern long get_int();
  49.     extern void set_int();
  50.     extern int _dsval, _csval;
  51.     register int_handler *new_handler;
  52.     void *malloc();
  53.     void common();        /* common interrupt handler code */
  54.  
  55.     /* allocate a new handler */
  56.     if (NULL == (new_handler = malloc(sizeof(int_handler))))
  57.         return NULL;
  58.  
  59.     /* copy template via structure assignment */
  60.     *new_handler = template;
  61.  
  62.     /* initialize the mov bx,seg service instruction */
  63.     new_handler->esfix.immed_data = 
  64. #ifdef LONGPTR
  65.                                     segment(new_handler);
  66. #else
  67.                                     _dsval;
  68. #endif
  69.  
  70.     /* initialize the mov bx, offset service instruction */
  71.     new_handler->svctobx.immed_data = offset(&(new_handler->new_offset));
  72.  
  73.     /* initialize the call far common instruction */
  74.     new_handler->func_call.offset = offset(common);
  75.     new_handler->func_call.segment =
  76. #ifdef FARPROC
  77.                                         segment(common);
  78. #else
  79.                                         _csval;
  80. #endif
  81.  
  82.     /* initialize the vector field of new_handler structure */
  83.     new_handler->new_offset = offset(handler);
  84.     new_handler->new_segment =
  85. #ifdef FARPROC
  86.                                 segment(handler);
  87. #else
  88.                                 _csval;
  89. #endif
  90.     int_vector.vector = get_int(int_num);
  91.  
  92.     /* save old segment */
  93.     new_handler->old_offset = int_vector.parts.offset;
  94.     new_handler->old_segment = int_vector.parts.segment;
  95.  
  96.     /* if we're supposed to chain to old interrupt call, change iret to
  97.        call far.  Since I store old vector right after iret, what could be
  98.        simpler ?
  99.      */
  100.     if (chain_int)
  101.         new_handler->iret = 0xEA;    /* jmp inter-segment direct */
  102.  
  103.     /* set up new vector */
  104.     set_int(int_num,offset(new_handler),segment(new_handler));
  105.     return new_handler;
  106. }
  107.  
  108. restore_handler(int_num,handler)
  109.     int int_num;
  110.     int_handler *handler;
  111. {
  112.     extern void set_int();
  113.     set_int(int_num,handler->old_offset,handler->old_segment);
  114.     free(handler);
  115. }
  116.  
  117. /*
  118.  * offset and segment used to isolate pointer components
  119.  */
  120. static offset(ptr)
  121. #ifdef LONGPTR
  122.     unsigned long ptr;
  123. {
  124.     return (int)(0x0000FFFF & ptr);
  125. }
  126. #else
  127.     unsigned ptr;
  128. {
  129.     return ptr;
  130. }
  131. #endif
  132.  
  133. static segment(ptr)
  134. #ifdef LONGPTR
  135.     unsigned long ptr;
  136. {
  137.     return (int) (0x0000FFFF & (ptr >> 16));
  138. }
  139. #else
  140. {
  141.     extern int _dsval;
  142.     return _dsval;
  143. }
  144. #endif
  145.